#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @time: 2021/9/6 16:35
# @Author : Admin
import datetime
import os
import platform
import re
import subprocess
import time
import zipfile
from configparser import ConfigParser

from framework.utils.log_record_util import get_logger
_logger = get_logger("common.util")

system_type = platform.system()


def wait_for_device(serial_no, timeout=180):
    '''等待设备连接
    '''
    _logger.info("adb -s %s wait-for-device" % serial_no)
    # os.system("timeout %d adb -s %s wait-for-device" % (timeout, serial_no))
    # os.system("adb -s %s wait-for-device" % (serial_no))
    d = get_model(serial_no)
    _logger.info("device:"+d)
    if len(d)<2:
        _logger.error("adb -s %s wait-for-device timeout" % serial_no)
        return False
    else:
        return d

def exec_cmd(cmd):
    """
    执行cmd命令
    :param cmd: 命令
    :return: 输出结果
    """
    if system_type.lower() == "windows":
        cmd = cmd.replace("grep ", "findstr ")
    print(cmd)
    r = os.popen(cmd)
    text = r.read()
    r.close()
    return text


def shell(serial, args):
    """
    执行adb shell命令
    :param serial: 设备序列号
    :param args: shell命令
    :return: 输出结果
    """
    cmd = "adb -s %s shell %s" % (serial, str(args))
    if system_type.lower() == "windows":
        cmd = cmd.replace("grep ", "findstr ")

    return subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)


def run_cmd(cmd):
    if system_type.lower() == "windows":
        cmd = cmd.replace("grep ", "findstr ")
        cmd = cmd.replace("rm ", "delete ")
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    result = process.stdout.read().strip().decode()
    if "procrank" in cmd:
        pass
    else:
        _logger.info(result)
    return result


def get_android_version(serial_no):
    result = run_cmd("adb -s %s shell getprop ro.product.firmware" % serial_no)
    # result = run_cmd("adb -s %s shell getprop ro.vendor.mediatek.version.release" % serial_no)
    if len(result) == 0:
        return run_cmd("adb -s %s shell getprop ro.custom.build.version" % serial_no)
    return result

def get_android_version_all(serial_no):
    result_list = []
    result = run_cmd("adb -s %s shell getprop ro.product.firmware" % serial_no)
    result_list.append("ro.product.firmware:" + result)

    result = run_cmd("adb -s %s shell getprop gsm.version.baseband]" % serial_no)
    result_list.append("gsm.version.baseband:" + result)

    result = run_cmd("adb -s %s shell gsm.version.ril-impl" % serial_no)
    result_list.append("gsm.version.ril-impl:" + result)

    result = run_cmd("adb -s %s shell persist.apr.cp2version]" % serial_no)
    result_list.append("persist.apr.cp2version:" + result)

    result = run_cmd("adb -s %s shell persist.apr.gpsversion]" % serial_no)
    result_list.append("persist.apr.gpsversion:" + result)

    return result_list

def read_config(cfg_file):
    cfg = ConfigParser()
    cfg.read(cfg_file, encoding="utf-8")
    return cfg


# 获取手机序列号
def get_fastboot_serial():
    output = run_cmd('fastboot devices')
    out_array = output.strip().split('\n')
    device_array = []
    for i in range(0, len(out_array)):
        if out_array[i].find('fastboot') != -1:
            device_array.append(out_array[i].split('\t')[0])
    return device_array


# 获取设备序列号
def get_serial():
    output = run_cmd('adb devices')
    out_array = output.strip().split('\n')
    device_array = []
    for i in range(0, len(out_array)):
        if out_array[i].find('device') != -1 and out_array[i].find("devices") == -1:
            device_array.append(out_array[i].split('\t')[0])
    return device_array


# def get_current_time():
#     current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
#     _logger.info("time:%s" % current_time)
#     return current_time

def getTimeStamp(time_str,format):
    timeArray = time.strptime(time_str, format)
    # 转换成时间戳
    return time.mktime(timeArray)

def getCurrentTimeUnderline():
    return time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime(time.time()))

def get_current_time_format():
    now = datetime.datetime.now()
    # return now.strftime("%Y%m%d%H%M%S")
    return now.strftime("%Y%m%d%H%M")

def formatTimeStamp(timestamp):
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp))

def getCurrentTime():
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))

def get_battery(serial_no):
    result = run_cmd("adb -s %s shell dumpsys battery | grep level" % serial_no)
    return result.lstrip("level:")


def get_model(serial_no):
    result = run_cmd("adb -s %s shell getprop ro.platform.model" % serial_no)
    if not result:
        result = run_cmd("adb -s %s shell getprop ro.product.model" % serial_no)
    return result.strip()


def install_app(serial_no, path):
    result = run_cmd("adb -s %s install %s" % (serial_no, path))
    return result


def get_installed_apklist(serial_no):
    out = run_cmd("adb -s %s shell pm list package -3" % serial_no)
    return out.strip().replace("package:", "").split()


def wait_appear_launcher(serial_no):
    count = 0
    while count < 6:
        out = run_cmd('adb -s %s shell "dumpsys activity | grep mFocusedActivity"' % serial_no)
        print(out)
        if "com.android.launcher" in out:
            break
        count += 1
        time.sleep(10)


def get_screen_size(serial_no):
    x = 0
    y = 0
    out = run_cmd("adb -s %s shell wm size" % serial_no)
    for line in out.split("\n"):
        if "Physical size:" in line:
            size = line.split("size:")[1]
            x = int(size.split("x")[0]) / 2
            y = int(size.split("x")[1]) / 2
            break
    return x, y


def write_file(filename, content, is_cover=False):
    '''
    写入文件 覆盖写入
    :param filename:
    :param content:
    :param is_cover:是否覆盖写入
    :return:
    '''
    try:
        newstr = ""
        if isinstance(content, list or tuple):
            for str1 in content:
                newstr = newstr + str1 + "\n"
        else:
            newstr = content

        if is_cover:
            file_mode = "wb"
        else:
            file_mode = "ab"
        with open(filename, file_mode) as f_w:
            # 通过write方法写文件时需要传入byte类型
            # 1.str转换为byte需要调用str.encode("utf-8")
            # 2.byte转换为str需要调用byte.decode()
            f_w.write(newstr.encode("utf-8"))
            _logger.debug('写{}文件完成'.format(filename))
    except Exception as e:
        _logger.info('{}写入异常!{}'.format(filename, e))


def mk_dir(foldername):
    '''
    创建文件目录
    :return:
    '''
    try:
        if not os.path.exists(foldername):
            os.makedirs(foldername)
            # subprocess.call("mkdir {}".format(foldername), shell=True)
            _logger.info('创建{}完成!'.format(foldername))
    except Exception as e:
        _logger.info('创建{}异常!'.format(foldername, e))

def read_file(filename):
    '''
    读取文件
    :return:
    '''
    result = ''
    try:
        with open(filename, "r") as f_r:
            result = f_r.read()
    except Exception as e:
        _logger.info('{}读取异常!{}'.format(filename, e))
    finally:
        return result


def get_appinfo_by_package(package):
    """
    通过包名获取应用的名称和版本
    :param package:包名
    :return:应用的名称和版本
    """
    component = "系统"
    version = ''
    if package != "":
        with open("appinfo.txt", 'r') as f:
            lines = f.readlines()
        for line in lines:
            if line.find(package) != -1:
                component = line.split("/")[1].strip()
                version = line.split("/")[2].strip()
                break
    return component, version


# 获取设备信息
def get_properties(logpath):
    """
    从properties文件中获取设备的属性
    :param logpath: 文件路径
    :return:属性字典
    """
    property_dict = {}
    property_dict["model"] = ""
    property_dict["pn"] = ""
    property_dict["version"] = ""
    property_dict["bios"] = ""
    property_dict["monitor"] = ""
    with open("%s/properties.txt" % logpath, "r") as f:
        lines = f.readlines()
    for line in lines:
        if line.find("ro.product.model") != -1:
            property_dict["model"] = line.split(": [")[1].split("]")[0].strip()
        if property_dict["model"] == "M50":
            property_dict["bios"] = "31(CR)"
            property_dict["monitor"] = "1.00T(R)"
        if line.find("ro.fac.cfg.PN") != -1:
            property_dict["pn"] = line.split(": [")[1].split("]")[0].strip()
        elif line.find("ro.serialno") != -1:
            property_dict["pn"] = line.split(": [")[1].split("]")[0].strip()
        elif line.find("ro.custom.build.version") != -1:
            property_dict["version"] = line.split(": [")[1].split("]")[0].strip()
        elif line.find("ro.vendor.mediatek.version.release") != -1:
            property_dict["version"] = line.split(": [")[1].split("]")[0].strip()
        elif line.find("pax.sp.BIOS") != -1:
            property_dict["bios"] = line.split(": [")[1].strip()[0:-1]
        elif line.find("pax.sp.MONITOR") != -1:
            property_dict["monitor"] = line.split(": [")[1].split("]")[0].strip()
        elif line.find("test_type:") != -1:
            property_dict["test_type"] = line.split(":")[1].strip()
        elif "start_time:" in line:
            property_dict["start_time"] = line.split(":")[1].strip()
        elif "end_time:" in line:
            property_dict["end_time"] = line.split(":")[1].strip()
        elif "whitelist:" in line:
            property_dict["whitelist"] = line.split(":")[1].strip()
        elif line.find("test_type:") != -1:
            property_dict["test_type"] = line.split("test_type:")[1].strip()
    return property_dict


def zip_file(filename, file_list):
    """
    压缩文件夹
    :param filename: 压缩包的名字
    :param file_list:
    """
    # zipfile.ZIP_DEFLATED为压缩，默认模式不压缩
    z = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
    for file in file_list:
        if os.path.isdir(file):
            for root, dirs, files in os.walk(file):
                for filespath in files:
                    z.write(os.path.join(root, filespath))
        else:
            z.write(file)
    z.close()


def search(path, filename):
    """
    在path目录下全局搜索filename文件
    :param path:目录
    :param filename:文件名
    :return:文件的路径
    """
    # 获取logkeyword路径
    found_file = []
    for fn in os.listdir(path):
        fp = os.path.join(path, fn)
        if os.path.isfile(fp) and fn.startswith(filename) and (not fn.endswith('~')):
            found_file.append(fp.replace('\\', '/'))
        elif os.path.isdir(fp):
            child_folder_res = search(fp, filename)
            if len(child_folder_res) > 0:
                for i in range(0, len(child_folder_res)):
                    found_file.append(child_folder_res[i].replace('\\', '/'))
    return found_file


def get_time_diff(start_time, end_time):
    """
    计算时间差
    :param start_time: 开始时间
    :param end_time: 结束时间
    :return: 时间差
    """
    start = time.strptime(start_time, "%Y%m%d%H%M%S")
    end = time.strptime(end_time, "%Y%m%d%H%M%S")
    test_time = int(time.mktime(end)) - int(time.mktime(start))
    r_time = int(test_time) / 60
    if r_time > 60:
        r_time = "%.2f" % (r_time / 60)
        diff_time = str(r_time) + " 小时"
    else:
        r_time = "%.2f" % r_time
        diff_time = str(r_time) + "分钟"
    return diff_time


def get_mk_time():
    current_time = time.strptime(time.strftime("%Y%m%d %H:%M:%S"), "%Y%m%d %H:%M:%S")
    # current_time = time.strptime(time.strftime("%Y%m%d %H:%M"), "%Y%m%d %H:%M:%S")
    return time.mktime(current_time)


def get_prop(serial_no, logpath):
    """
    获取设备的属性，并写入properties文件夹
    :param serial_no: 设备序列号
    :param logpath:保存文件的路径
    """
    p = subprocess.Popen("adb -s %s shell getprop" % serial_no, shell=True, stdout=subprocess.PIPE)
    out = p.stdout.readlines()
    with open("%s/properties.txt" % logpath, "w") as f:
        for line in out:
            try:
                line = line.decode().strip()
                f.write(line + "\n")
            except UnicodeDecodeError as e:
                pass
            continue

BaseDir=os.path.dirname(os.path.abspath(__file__))
def get_top_dir():
    dir = os.path.dirname(BaseDir)
    path = os.path.dirname(dir)
    print("path:%s" % path)
    return path


def get_dir_list(path):
    """
    获取路径下的所有目录名称
    :param path:路径
    :return:目录名称列表
    """
    p_list = []
    path_list = os.listdir(path)
    for p in path_list:
        if os.path.isdir(os.path.join(path, p)):
            p_list.append(p)
    return p_list

def get_FileSize(filePath):
    '''
    获取文件的大小,结果保留4位小数，单位为MB
    :param filePath:
    :return:
    '''
    fsize = os.path.getsize(filePath)
    fsize = fsize / float(1024 * 1024)
    return round(fsize, 4)

def get_files(path=None, pattern=None):
    '''
    :param path: 目录
    :param pattern: 正则
    :return: 递归遍历目录，返回匹配的文件路径
    '''
    file_list = []
    if path is None or not os.path.exists(path): #没有路径返回空
        return file_list
    for oneFile in os.listdir(path):
        if os.path.isfile(os.path.join(path, oneFile)):
            match = False
            if pattern:
                match = re.match(pattern, oneFile, flags=0)
            if match:
                file_list.append(os.path.join(path, oneFile)) #是文件 且匹配正则成功 则添加文件
        elif os.path.isdir(os.path.join(path, oneFile)):
            file_list.extend(get_files(os.path.join(path, oneFile), pattern)) #是文件夹 遍历下一级目录下 符合正则的文件 并追加
    return file_list


def get_FileSize(filePath):
    '''
    获取文件的大小,结果保留4位小数，单位为MB
    :param filePath:
    :return:
    '''
    fsize = os.path.getsize(filePath)
    fsize = fsize / float(1024 * 1024)
    return round(fsize, 4)


def get_FileAccessTime(filePath):
    '''获取文件的访问时间'''
    t = os.path.getatime(filePath)
    return t


def get_FileCreateTime(filePath):
    '''获取文件的创建时间'''
    t = os.path.getctime(filePath)
    return t


def get_FileModifyTime(filePath):
    '''获取文件的修改时间'''
    t = os.path.getmtime(filePath)
    return t


def get_project_name(serial_no):
    output = exec_cmd("adb -s %s shell getprop ro.product.model" % serial_no)
    return output.strip()


def get_screenon(serial_no):
    # 获取有没有这个设备
    adb_device = 'adb devices'
    with os.popen(adb_device) as f:
        res = f.read()
    if serial_no not in res:
        return False

    # 获取屏幕亮灭状态
    if system_type.lower() == "windows":
        adb = 'adb -s %s shell dumpsys window policy|findstr screenState' % serial_no
    else:
        adb = 'adb -s %s shell dumpsys window policy|grep screenState' % serial_no

    with os.popen(adb) as f:
        res = f.read()

    if 'SCREEN_STATE_OFF' in res:
        print('设备灭屏，开启屏幕')
        # 熄灭屏幕223，点亮屏幕224
        os.system('adb -s %s shell input keyevent 224' % serial_no)
        time.sleep(1)
        os.system('adb -s %s shell input swipe 357 1145 357 369' % serial_no)
        os.system('adb -s %s shell input keyevent 25' % serial_no) #调低音量
        return True



def get_pid(device, process_name):
    result = run_cmd('adb -s %s shell "ps -A | grep %s"' % (device, process_name))
    if result == "":
        result = run_cmd('adb -s %s shell "ps | grep %s"' % (device, process_name))
    if result != "":
        pid_list = result.split()
        return pid_list[1]
    else:
        return ""


def get_product(device):
    return run_cmd("adb -s %s shell getprop ro.build.product" % device)


def get_cpu_info(device):
    return run_cmd("adb -s %s shell getprop ro.product.cpu.abi" % device)


def get_build_date(device):
    return run_cmd('adb -s %s shell getprop ro.build.date.utc' % device)


def get_property(run_time, device):
    body_info = []
    body_info.append(run_time / 60)
    body_info.append(get_model(device))
    body_info.append(get_android_version(device))
    body_info.append(get_cpu_info(device))
    body_info.append(get_build_date(device))
    return body_info


def getactivity(self):
    """
    获取当前的Activity
    :return:当前的Activity
    获取当前Activity有出现异常的时候,此时返回'undefined'
    """
    try:
        if system_type.lower() == "windows":
            cmd = 'adb -s %s shell dumpsys activity | findstr "mFocusedActivity"' % self.dev
        else:
            cmd = 'adb -s %s shell dumpsys activity | grep "mFocusedActivity"' % self.dev
        result = os.popen(cmd)
        _logger.debug(cmd)
        act = str(result.readlines()).split('/')[1].split()[0]
        return act

    except Exception as e:
        _logger.error("GetActivity error! " + str(e))
        return 'undefined'


def getdevices(self):
    """
    获取设备id
    :return: 0表示未获取到,id是设备的真实id
    """
    try:
        cmd = "adb devices"
        pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
        id = pipe.read().split()[-2]
        if id != 'devices':
            return id
        else:
            _logger.info("List of devices attached")
            return 0

    except Exception as e:
        _logger.error("the process doesn't exist." + str(e))
        return 0


def get_app_pid(self, pkg_name):
    """
    根据包名得到进程id
    :return: 0表示未获取到,pid是设备的真实pid
    """
    try:
        if system_type.lower() == "windows":
            cmd = "adb -s %s shell ps | findstr %s" % (self.dev, pkg_name)
        else:
            cmd = "adb -s %s shell ps | grep %s" % (self.dev, pkg_name)
        _logger.debug(cmd)

        pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
        pid = pipe.read().split()[1]
        return str(pid)
    except Exception as e:
        _logger.error("the process doesn't exist." + str(e))
        return 0


def get_app_pid(device_name, app_name):
    '''
    获取app的pid
    '''
    pid = ''
    try:
        if system_type.lower() == "windows":
            cmd = 'adb -s {} shell ps | findstr {}'.format(device_name, app_name)
        else:
            cmd = 'adb -s {} shell ps | grep {}'.format(device_name, app_name)
        pid = os.popen(cmd).readlines()[0].split()[1]
    except Exception as e:
        _logger.error("获取当前activity异常!{}".format(e))
        _logger.info("获取当前activity异常!{}".format(e))
    finally:
        return pid


def get_app_uid(self, pkg_name):
    """
    根据包名得到进程id
    :return: 0表示未获取到,uid是设备的真实uid
    """
    try:
        cmd = "adb -s %s shell cat /proc/%s/status" % (self.dev, self.get_app_pid(pkg_name))
        _logger.debug(cmd)

        pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout
        for index in pipe.readlines():
            if index.startswith('Uid'):
                return index.split()[1]
    except Exception as e:
        _logger.error("the process doesn't exist." + str(e))
        return 0


def pull_file(device, remotefile, localfile):
    '''
    把crashlog pull到本地
    :return:
    '''
    try:
        cmd = 'adb -s {} pull {} {}'.format(device, remotefile, localfile)
        _logger.info('拉取文件命令:{}'.format(cmd))
        os.system(cmd)
        # subprocess.Popen(cmd, shell=True)
    except Exception as e:
        _logger.info('拉取文件异常:{}'.format(e))


def push_file(device, localfile, remotefile):
    '''
    push本地文件到设备
    :return:
    '''
    try:
        cmd = 'adb -s {} push {} {}'.format(device, localfile, remotefile)
        _logger.info('push本地文件到设备命令:{}'.format(cmd))
        subprocess.call(cmd, shell=True)
    except Exception as e:
        _logger.info('push本地文件异常:{}'.format(e))


def kill_pid(keyword):
    '''
    结束进程
    :param keyword:
    :return:
    '''
    try:
        if system_type.lower() == "windows":
            cmd = "ps -ef | grep {} | findstr -v grep".format(keyword)
        else:
            cmd = "ps -ef | grep {} | grep -v grep".format(keyword)
        pids = os.popen(cmd).read()
        if pids == '' or pids == None:
            _logger.info("未查询到pid")
        else:
            pids = str(pids).split()[1]
            subprocess.call("kill -9 {}".format(pids), shell=True)
            _logger.info("结束:{},进程号:{}".format(keyword, pids))
    except Exception as e:
        _logger.info("kill pid异常!{}".format(e))


def unlock_screen(device):
    '''
    唤醒屏幕
    :return:
    '''
    result = os.popen("adb -s {} shell dumpsys window policy "
                      "| grep isStatusBarKeyguard".format(device)).readlines()
    if "isStatusBarKeyguard=true" in result[0]:
        _logger.info("screen start wakup!")
        os.system("adb shell input keyevent 26")
    else:
        _logger.info("screen already wakup!")


def del_files(filesname):
    '''
    删除文件
    :param filesname:
    :return:
    '''

    try:
        if os.path.exists(filesname):
            subprocess.call("rm -rf {}".format(filesname), shell=True)
        _logger.info("删除{}完成!".format(filesname))
    except Exception as e:
        _logger.info("删除文件异常!".format(e))


def format_time(time_str):
    '''
    格式化时间
    :param time_str:
    :return:
    '''
    try:
        if re.findall('total', time_str):
            time_str = time_str.replace('ms', '')
            time_str = time_str.split('(')[0].strip()
            if re.findall('s', time_str):
                new_time_m = str(time_str).split('s')[0]
                new_time_s = str(time_str).split('s')[1]
                new_time = int(new_time_m) * 1000 + int(new_time_s)
            else:
                new_time = time_str
        else:
            time_str = time_str.replace('ms', '')
            if re.findall('s', time_str):
                new_time_m = str(time_str).split('s')[0]
                new_time_s = str(time_str).split('s')[1]
                new_time = int(new_time_m) * 1000 + int(new_time_s)
            else:
                new_time = time_str
    except Exception as e:
        _logger.error('格式化时间异常!{}'.format(e))
        new_time = 0
    finally:
        return new_time


def get_current_activity(device_name):
    '''
    获取当前的Activity
    '''
    activity = 'undefined'
    try:
        if system_type.lower() == "windows":
            cmd = 'adb -s {} shell dumpsys activity | findstr "mFocusedActivity"'.format(device_name)
        else:
            cmd = 'adb -s {} shell dumpsys activity | grep "mFocusedActivity"'.format(device_name)
        # cmd = 'adb -s {} shell dumpsys activity | findstr "mFocusedActivity"'.format(device_name)
        # cmd = 'adb -s {} shell dumpsys window | findstr mCurrentFocus'.format(device_name)
        r = os.popen(cmd)
        # 以上命令获取内容如下：需要提取出com.android.dialer.main.impl.MainActivity
        # 'mCurrentFocus=Window{41b8b76 u0 com.android.dialer/com.android.dialer.main.impl.MainActivity}'
        text = r.read()
        # _logger.info("text: {}".format(text))
        m = text.split('/')
        n = m[1].split('}')
        activity = n[0]
        _logger.debug("activity: {}".format(n[0]))
        # activity = str(os.popen(cmd).readlines()).split('/')[1].split()[0]
        # _logger.info("activity: {}".format(activity))
    except Exception as e:
        _logger.info("获取当前activity异常!{}".format(e))
    finally:
        return activity


def get_app_uid(device_name, pkg_name):
    '''
    根据包名得到进程id
    :return: 0表示未获取到,uid是设备的真实uid
    '''
    uid = ''
    try:
        pid = get_app_pid(device_name, pkg_name)
        cmd = "adb -s {} shell cat /proc/{}/status".format(device_name, pid)
        result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE).stdout.readlines()
        for line in result:
            if line.startswith('Uid'):
                uid = line.split()[1]
    except Exception as e:
        _logger.error("获取进程id异常{}".format(e))
    finally:
        return uid


def ms2s(value):
    return round(value/1000.0, 2)

def transfer_temp(temp):
    return round(temp/10.0,1)

def mV2V(v):
    return round(v/1000.0,2)

def uA2mA(c):
    return round(c/1000.0,2)